package com.sebscape.sebcms.tools;

import com.sebscape.sebcms.Constants;

import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.ParseException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * User: Steve
 * Date: Jan 2, 2006
 * Time: 02:39:09 AM
 */

/**
 * DateUtils
 */
public class DateUtils {

	private static Log log = LogFactory.getLog( DateUtils.class );
	
    ////////////////////////////////////////////////////////
    // Constructors
    ////////////////////////////////////////////////////////

    /**
     * Default Constructor
     */
    public DateUtils() {

    }

    public Date updateTime(Date date, Date timeHolder){
        Calendar cal = new GregorianCalendar();
        cal.setTime( date );
        int hours = Integer.parseInt( new SimpleDateFormat( "h" ).format( timeHolder ) );
        int minutes = Integer.parseInt( new SimpleDateFormat( "M" ).format( timeHolder ) );
        cal.set( Calendar.HOUR, hours );
        cal.set( Calendar.MINUTE, minutes );
        return cal.getTime();
    }

    public Date updateDate(Date date, Date dateHolder){
        Calendar cal = new GregorianCalendar();
        cal.setTime( date );
        int month = Integer.parseInt( new SimpleDateFormat( "m" ).format( dateHolder ) );
        int day = Integer.parseInt( new SimpleDateFormat( "d" ).format( dateHolder ) );
        int year = Integer.parseInt( new SimpleDateFormat( "yyyy" ).format( dateHolder ) );
        cal.set( Calendar.MONTH, month );
        cal.set( Calendar.DAY_OF_MONTH, day );
        cal.set( Calendar.YEAR, year );
        return cal.getTime();
    }

    public static Date getDatetimeFromString( String format, String datetimeAsString ){
        try {
            DateFormat formatter = new SimpleDateFormat( format );
            return formatter.parse( datetimeAsString );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Date getDateFromString( String datetimeAsString ){
        return getDatetimeFromString( "yyyy-MM-dd", datetimeAsString );
    }

    public static Date getTimeFromString( String militaryTimeAsString ){
        return getDatetimeFromString( "hhMM", militaryTimeAsString );
    }

    public static void main(String[] args) {
        //Calendar calendar = new GregorianCalendar();
        try {
            Date date = new SimpleDateFormat( Constants.DEFAULT_DATE_FORMAT ).parse( "01/01/06" );
            log.debug("add 3 months = " + changeDate( date, Calendar.MONTH, 3 ) );
            log.debug("last day of week = " + getLastDateOfWeek( date, Calendar.MONDAY, false ) );
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * For exmample if you wanted to compute what day of the week is Saturday on a calendar where monday
     * begins the week, you would pass javaDayValue = Calendar.SATURDAY and firstDayOfWeek = Calendar.MONDAY.
     * @param javaDayValue
     * @param firstDayOfWeek
     * @return converted day
     */
    public static int dayOfWeekShifter( int javaDayValue, int firstDayOfWeek ){
        return ( ( javaDayValue - ( 6 + firstDayOfWeek ) ) % 7 ) + 7;
    }

    /**
     * This is a version of the Calendar add() method for adding or subtracting days, months, years, etc., only this
     * method passes Date Objects in and out.
     * @param oldDate
     * @param calendarField
     * @param amount
     * @return Date.
     */
    public static Date changeDate( Date oldDate, int calendarField, int amount ){
        Calendar cal = new GregorianCalendar();
        cal.setTime( oldDate );
        cal.add( calendarField, amount );
        return cal.getTime();
    }

    public static Date getFirstDateOfMonth( Date date, boolean rollTime ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.set( Calendar.DATE, 1 );
        if ( rollTime)
            return getDayBegin( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getLastDateOfMonth(Date date, boolean rollTime  ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.add( Calendar.MONTH, 1 );
        calendar.set( Calendar.DATE, 1 );
        calendar.add( Calendar.DATE, -1 );
        if ( rollTime )
            return getDayEnd( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getFirstDateOfWeek( Date date, boolean rollTime ){
        return getFirstDateOfWeek( date, Calendar.SUNDAY, rollTime );
    }

    public static Date getFirstDateOfWeek( Date date, int firstDayOfWeek, boolean rollTime ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.add( Calendar.DAY_OF_MONTH, -( dayOfWeekShifter( calendar.get( Calendar.DAY_OF_WEEK ), firstDayOfWeek ) - 1 ) );
        if ( rollTime )
            return getDayBegin( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getLastDateOfWeek( Date date, boolean rollTime ){
        return getLastDateOfWeek( date, Calendar.SUNDAY, rollTime );
    }

    public static Date getLastDateOfWeek( Date date, int firstDayOfWeek, boolean rollTime ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.add( Calendar.DAY_OF_WEEK, 7 - dayOfWeekShifter( calendar.get( Calendar.DAY_OF_WEEK ), firstDayOfWeek ) - 1 );
        if ( rollTime )
            return getDayEnd( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getFirstDateOfYear( Date date, boolean rollTime ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.set( Calendar.MONTH, Calendar.JANUARY );
        calendar.set( Calendar.DATE, 1 );
        if ( rollTime )
            return getDayBegin( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getLastDateOfYear( Date date, boolean rollTime ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.add( Calendar.YEAR, 1 );
        calendar.setTime( getFirstDateOfYear( calendar.getTime(), false ) );
        calendar.add( Calendar.DATE, -1 );
        if ( rollTime )
            return getDayEnd( calendar.getTime() );
        else
            return calendar.getTime();
    }

    public static Date getDayBegin( Date date ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.set( Calendar.HOUR_OF_DAY, 0);
        calendar.set( Calendar.MINUTE, 0 );
        calendar.set( Calendar.SECOND, 0 );
        calendar.set( Calendar.MILLISECOND, 0 );
        return calendar.getTime();
    }

    public static Date getDayEnd(Date date){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( date );
        calendar.set( Calendar.HOUR_OF_DAY, 23);
        calendar.set( Calendar.MINUTE, 59 );
        calendar.set( Calendar.SECOND, 59 );
        return calendar.getTime();
    }

    public static Date getFollowingMonth( Date pivotDate ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( pivotDate );
        calendar.add( Calendar.MONTH, 1 );
        return calendar.getTime();
    }

    public static Date getPreceedingMonth( Date pivotDate ){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime( pivotDate );
        calendar.add( Calendar.MONTH, -1 );
        return calendar.getTime();
    }

}
